﻿using System.IO;
using System;
using UnityEngine;

namespace xuni
{


    public static class IOUtils
    {


        public static string Byte2ReadableUnit(long bytes)
        {
            string[] names = new string[] { "B", "KB", "MB", "GB", "TB", "PB" };
            var unitIndex = 0;
            double tempBytes = bytes;
            while (tempBytes >= 1024)
            {
                tempBytes /= 1024;
                ++unitIndex;
                if (unitIndex + 1 >= names.Length)
                    break;
            }

            var sb = StringUtils.Builder;

            var str = sb.Append(tempBytes).ToString();
            var dotNum = -1;
            var i = 0;
            for (; i < str.Length; ++i)
            {
                var c = str[i];
                if ('.' == c)
                {
                    dotNum = 0;
                }
                else
                {
                    //小数点后2位
                    if (dotNum >= 0)
                    {
                        dotNum++;
                        if (dotNum > 2)
                        {
                            break;
                        }
                    }
                }
            }
            var diff = sb.Length - i;
            if (diff > 0)
                sb.Remove(i, diff);

            return sb.Append(names[unitIndex]).BuildString();
        }


        public static bool FlushAndClose(Stream s)
        {
            if (null == s)
                return false;

            try
            {
                s.Flush();
                s.Close();
                s.Dispose();
            }
            catch (Exception ex)
            {
                // do nothing
            }
            return true;
        }


        public static bool SafeClose(Stream s)
        {
            if (null == s)
                return false;

            try
            {
                s.Close();
                s.Dispose();
            }
            catch (Exception ex)
            {
                //do nothing
            }
            return true;
        }


        public static void BackupFile(string file)
        {
            if (!File.Exists(file))
            {
                Debug.Log($"to backup file not exist: {file}");
                return;
            }

            var bakFile = StringUtils.Builder.Append(file).Append("-bak").BuildString();
            if (File.Exists(bakFile))
            {
                File.Delete(bakFile);
            }
            File.Move(file, bakFile);
        }


        public static void RestoreBackupFile(string file)
        {
            var bakFile = StringUtils.Builder.Append(file).Append("-bak").BuildString();
            if (!File.Exists(bakFile))
            {
                Debug.Log($"to restore file not exist: {file}");
                return;
            }

            if (File.Exists(file))
                File.Delete(file);

            File.Move(bakFile, file);
        }


        public static void MoveFile(string srcFilePath, string moveToDir, bool moveMeta)
        {
            MoveFile(srcFilePath, moveToDir, moveMeta, out var dstFilePath);
        }

        public static bool MoveFile(string srcFilePath, string moveToDir, bool moveMeta, out string dstFilePath)
        {
            dstFilePath = null;
            if (!File.Exists(srcFilePath))
            {
                Debug.LogError($"MoveFile: src not exists: {srcFilePath} => {moveToDir}");
                return false;
            }

            var sb = StringUtils.Builder;

            moveToDir = sb.Append(moveToDir).Replace('\\', '/').BuildString();
            moveToDir = PathUtils.DirEndWithSeparator(moveToDir);
            if (!Directory.Exists(moveToDir))
                Directory.CreateDirectory(moveToDir);

            var tempDstFilePath = sb.Append(moveToDir).Append(Path.GetFileName(srcFilePath)).BuildString();
            if (File.Exists(tempDstFilePath))
            {
                srcFilePath = sb.Append(srcFilePath).Replace('\\', '/').BuildString();
                if (srcFilePath == tempDstFilePath)
                {
                    //Debug.Log($"MoveFile: same dir: {srcFilePath}");
                }
                else
                    Debug.LogError($"MoveFile: dst exists: {srcFilePath} => {tempDstFilePath}");

                return false;
            }


            Debug.Log($"{srcFilePath} >>> [{tempDstFilePath}]");
            if (true) File.Move(srcFilePath, tempDstFilePath);

            if (moveMeta)
                MoveMetaFile(srcFilePath, tempDstFilePath);
            
            dstFilePath = tempDstFilePath;
            return true;
        }

        static void MoveMetaFile(string srcFilePath, string dstFilePath)
        {
            var sb = StringUtils.Builder;

            var srcMetaFile = sb.Append(srcFilePath).Append(".meta").BuildString();
            if (!File.Exists(srcMetaFile))
            {
                Debug.LogError($"MoveMetaFile: src not exists: {srcMetaFile}");
                return;
            }

            var dstMetaFile = sb.Append(dstFilePath).Append(".meta").BuildString();
            if (File.Exists(dstMetaFile))
            {
                Debug.LogError($"MoveMetaFile: dst exists: {srcMetaFile}, => {dstMetaFile}");
                return;
            }

            if (true) File.Move(srcMetaFile, dstMetaFile);
        }

    } //end of class


}
